package xworker.javafx.beans.binding;

import javafx.beans.binding.StringBinding;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import xworker.javafx.util.JavaFXUtils;

import java.util.ArrayList;
import java.util.List;

public class CaseStringBinding extends StringBinding {
    List<StringCase> caseList;

    public CaseStringBinding(List<StringCase> caseList){
        this.caseList = caseList;

        for(StringCase stringCase : caseList){
            this.bind(stringCase.condition);
        }
    }

    @Override
    protected String computeValue() {
        for(StringCase stringCase : caseList){
            if(stringCase.getCondition().getValue()){
                return stringCase.getValue();
            }
        }

        return null;
    }

    public static Object create(ActionContext actionContext){
        Thing self = actionContext.getObject("self");
        List<StringCase> caseList = new ArrayList<>();
        for(Thing child : self.getChilds("Case")){
            ObservableValue<Boolean> booleanValue = JavaFXUtils.getObject(child, "booleanValue", actionContext);
            if(booleanValue == null){
                throw new NullPointerException("boolean value is null, path=" + child.getMetadata().getPath());
            }
            Object stringValue = JavaFXUtils.getObject(child, "stringValue", actionContext);
            caseList.add(new StringCase(booleanValue, stringValue));
        }

        for(Thing child : self.getChilds("Default")){
            ObservableValue<Boolean> booleanValue = new SimpleBooleanProperty(true);
            Object stringValue = JavaFXUtils.getObject(child, "stringValue", actionContext);
            caseList.add(new StringCase(booleanValue, stringValue));
            break;
        }

        CaseStringBinding binding = new CaseStringBinding(caseList);
        actionContext.g().put(self.getMetadata().getName(), binding);
        actionContext.peek().put("parent", binding);

        for(Thing child : self.getChilds()){
            String thingName = child.getThingName();
            if(!"Case".equals(thingName) && !"Default".equals(thingName)){
                child.doAction("create", actionContext);
            }
        }

        return binding;
    }

    static class StringCase{
        ObservableValue<Boolean> condition;
        Object value;

        public StringCase(ObservableValue<Boolean> condition, Object value){
            this.condition = condition;
            this.value = value;
        }

        public ObservableValue<Boolean> getCondition(){
            return condition;
        }

        public String getValue(){
            if(value instanceof String){
                return (String) value;
            }else if(value instanceof ObservableValue){
                return String.valueOf(((ObservableValue<?>) value).getValue());
            }else if(value != null){
                return value.toString();
            }else{
                return null;
            }
        }
    }

}
